use std::{alloc::{GlobalAlloc, Layout}, ptr::NonNull, sync::{Arc, Mutex}, thread, time::Duration};

use aes::cipher::generic_array::typenum::uint;
use tokio::time::sleep;
use tokio_cron_scheduler::{Job, JobSchedulerError, JobToRunAsync};

use crate::primary::Animal::Dog;
pub mod primary_in {
    pub fn pp() {
        println!("i am pp");
    }
}
/**
* 一些Rust高级特性
*/
pub(crate) fn main() {
    // ownership();
    //  reference();
    //  slice();
    //  structure();
    //  method();
    // enum_and_match();
    // async_schedule();
    test_box_mem();
}
fn test_box_mem(){
    #[derive(Debug)]
    struct A(i32);

    impl Drop for A {
        fn drop(&mut self) {
            println!("drop A inner is {}", self.0);
        }
    }

    let a = Box::new(A(1));
    let raw = Box::into_raw(a);
    println!("raw = {:?}", raw);

    // unsafe { ptr::drop_in_place(raw) };
    let sys = std::alloc::System;
    unsafe {
        let layout = Layout::for_value(raw.as_ref().unwrap());
        println!("layout = {:?}", layout);
        let non = NonNull::new(raw).unwrap();
        GlobalAlloc::dealloc(&sys, raw.cast(), layout);
    }

    let a = Box::new(A(2));
    println!("raw2 = {:?}", a.as_ref() as *const A);

    println!("a = {:?}", unsafe{& *raw});
}

/// tokio 定时任务测试
fn tokio_cron_test(){
    let r = tokio::runtime::Runtime::new().unwrap();

    async fn do_cron()->Result<(), JobSchedulerError>{
        // 创建定时任务调度器
        let sche = tokio_cron_scheduler::JobScheduler::new().await.unwrap();
        // 添加定时任务
        let uuid = sche.add(Job::new_async("0/3 * * * * *", |uuid,mut _l|{
            Box::pin(async move{
                println!("i run every 3 seconds, uuid={}", uuid);
                println!("next tick at {:?}", _l.next_tick_for_job(uuid).await.unwrap());
            })
        })?).await
        .unwrap();
        // 开启定时任务
        sche.start().await?;
        
        println!("begin sleep");
        sleep(Duration::from_secs(10)).await;
        Ok(())
    }

    r.block_on(async{
        do_cron().await.unwrap();
        
    });
}
fn _async_schedule() {
    //两个线程时，两个任务回交替执行，
    // 一个线程时，如果不发生阻塞，一个任务执行完毕，另一个线程继续执行
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .worker_threads(1)
        .thread_name("my-")
        .enable_all()
        .build()
        .unwrap();
    let (rx, mut tx) = tokio::sync::mpsc::channel::<u32>(99999);
    let rx_c1 = rx.clone();
    // 异步任务发送0
    runtime.spawn(async move{
        for _ in 0..99 {
            sleep(Duration::from_millis(20)).await;
            rx_c1.send(0).await.unwrap();
        }
    });
    // 异步任务发送1
    runtime.spawn(async move{
        for _ in 0..99 {
            sleep(Duration::from_millis(20)).await;
            rx.send(1).await.unwrap();
        }
    });
    // 异步任务接收
    runtime.block_on(async move{
        while let Some(i) = tx.recv().await {
            println!("i = {}", i);
        }
    });
}
// 枚举和模式匹配
fn enum_and_match() {
    let dog = Animal::Dog {
        name: String::from("huanhuan"),
    };
    let cat = Animal::Cat(String::from("mimi"));
    dog.say_name();
    cat.say_name();

    let mut op1 = Some(5);
    // op1 = None;
    println!("op1 is some:{}", op1.is_some());
    println!("op1 value is {}", op1.unwrap_or(0));
    let no: Option<i32> = None;
    // println!("no value is {}", no.unwrap_or("haha"));
    println!("no value is {}", no.unwrap_or(12));
}
enum Animal {
    Dog { name: String },
    Cat(String),
    Mouse(String),
}
impl Animal {
    fn say_name(&self) {
        let s = match self {
            Dog { name } => {
                let mut string = "this is dog, name is ".to_string();
                string.push_str(name);
                string
            }
            Animal::Cat(str) => "this is cat, name is ".to_string(),
            Animal::Mouse(str) => "this is mouse".to_string(),
        };
        println!("s={}", s);
    }
}
struct Rectangle {
    width: u32,
    height: u32,
}
fn method() {
    let mut rec1 = Rectangle {
        width: 3,
        height: 4,
    };
    println!("rec1 area is {}", rec1.area());
    println!("rec1 area is {}", rec1.area());

    let rec2 = Rectangle::square(5);
    println!("rec2 area is {}", rec2.area());
}
impl Rectangle {
    // 属于结构体的 方法
    fn area(&self) -> u32 {
        let old_width = self.width;
        // self.width=4;
        old_width * self.height
    }
}
// impl块 可以有多个 效果都是一样的
impl Rectangle {
    // 关联函数 相当于 静态函数，不和实例绑定，没有 &self
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}
fn structure() {
    struct User {
        name: String,
        age: i16,
        email: String,
    }

    let user2 = User {
        name: "smith".to_string(),
        age: 16,
        email: "182@qq.comm".to_string(),
    };
    let name = "jack".to_string();
    let user = User {
        name: name.clone(), //1.name 绑定相同名称的变量赋值;2.name 如果使用.to_string() 重新创建值就不会有问题
        ..user2             // 其他属性使用user2 的属性
    };
    println!(
        "user: name={}, age={}, email={}",
        user.name, user.age, user.email
    );
    println!("name={}, user2.age={}", name, user2.age);

    struct Point(i32, i32, i32);
    struct Color(i32, i32, i32);
    // 结构体元组
    let p = Point(1, 2, 5);
    let c = Color(1, 2, 5);
    println!("Point.0 is {}, p.1 is {}", p.0, p.1);
    println!("Color.1 is {}, c.2 is {}", p.1, p.2);
}

fn slice() {
    let mut s = "hello world".to_string();
    let sli = &s[0..5];
    println!("{}", sli);
    // 后面不使用 sli就不会报错，应为不会影响sli的行为，所以这里可以修改s
    // s.clear();
    // println!("{}",sli);

    let arr = [4, 8, 9, 5, 6];
    let sli = &arr[1..4];
    println!("sli[0]: {}, sli[2]: {}", sli[0], sli[2]);
    for &ele in sli.iter() {
        println!("{}", ele);
    }
}

fn reference() {
    let mut s = "Kitty".to_string();
    let len = s_len(&s);
    println!("len of {} is {}", s, len);

    // let s2 = &mut s;
    let s2 = &s;
    // 多个可变引用 会报错
    let s3 = &s;
    println!("s2={}, s3={}", s2, s3);

    let s3 = &mut s;
    println!("s3={}", s3);
    // 可变使用完毕之后，可以声明不可变 不会报错
    let s2 = &s;
    println!("s2={}", s2);
}
fn s_len(str: &String) -> usize {
    // 不能修改值
    // str.push_str("dd");
    str.len()
}
fn ownership() {
    let x = 2;
    let y = x;
    println!("x={}, y={}", x, y);

    let s = String::from("hello world");
    let mut s2 = s;

    // s 的所有权已经移交 这里会报错
    // println!("s2={}, s={}",s2, s);
    // take_ownship(s2);
    s2 = take_ownship(s2);

    // 报错，s2 移交了所有权 给 take_ownship中的变量 str
    // 可以通过 函数返回 str 的方式 将所有权 重新移交给 s2
    println!("s2={}", s2);

    let s = "Kitty".to_string();
    let (s2, len) = cal_len(s);
    println!("s2={}, len={}", s2, len);
}

fn cal_len(str: String) -> (String, usize) {
    let len = str.len();
    (str, len)
}

// fn take_ownship(str: String){
fn take_ownship(str: String) -> String {
    println!("str={}", str);
    str
}
